import { dist, distancePoints, isNumber, vectorRotationSlope } from './base';

/**
 * 根据源锚点和目标锚点获取贝塞尔曲线控制点
 * @param {{p:{x:number, y:number},v:number|undefined}} sourceAnchor
 * @param {{p:{x:number, y:number},v:number|undefined}} targetAnchor
 * @returns
 */
export const getBezierCurveControlPoints = (sourceAnchor, targetAnchor) => {
  const { p: start, v: startV } = sourceAnchor;
  const { p: end, v: endV } = targetAnchor;
  let p1 = { x: (start.x + end.x) / 2, y: start.y };
  let p2 = { x: (start.x + end.x) / 2, y: end.y };
  const distance = (Math.abs(start.x - end.x) + Math.abs(start.y - end.y)) / 4;
  // let distance = Math.min(Math.abs(start.x - end.x), Math.abs(start.y - end.y)) / 2;
  // const minDist = dist(start, end) / 10;
  // if (distance <= minDist) distance = minDist;
  // 根据两端锚点射出角度获取控制点
  if (isNumber(startV)) p1 = distancePoints(start, vectorRotationSlope(startV), distance, startV)[0];
  if (isNumber(endV)) p2 = distancePoints(end, vectorRotationSlope(endV), distance, endV)[0];
  return [start, p1, p2, end];
};

/**
 * 根据贝塞尔曲线控制点获取路径
 * @param {{x:number, y:number}[]} controlPoints 控制点
 * @returns
 */
export const getBezierCurvePath = (controlPoints) => {
  const [p0, p1, p2, p3] = controlPoints;
  const path = new Path2D();
  path.moveTo(p0.x, p0.y);
  path.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
  return path;
};

/**
 * 根据贝塞尔曲线控制点和曲线进度获取点坐标
 * @param {{x:number, y:number}[]} controlPoints 控制点
 * @param {number} t 曲线进度
 * @returns
 */
export const getBezierCurvePoint = (controlPoints, t) => {
  const [p0, p1, p2, p3] = controlPoints;
  // 贝塞尔曲线方程
  const x =
    Math.pow(1 - t, 3) * p0.x +
    3 * Math.pow(1 - t, 2) * t * p1.x +
    3 * (1 - t) * Math.pow(t, 2) * p2.x +
    Math.pow(t, 3) * p3.x;
  const y =
    Math.pow(1 - t, 3) * p0.y +
    3 * Math.pow(1 - t, 2) * t * p1.y +
    3 * (1 - t) * Math.pow(t, 2) * p2.y +
    Math.pow(t, 3) * p3.y;
  return { x, y };
};

/**
 * 根据贝塞尔曲线控制点获取路径点坐标
 * @param {{x:number, y:number}[]} controlPoints 控制点
 * @param {number} frequency 分割曲线的步频
 * @returns
 */
export const getBezierCurvePoints = (controlPoints, frequency = 1) => {
  if (frequency >= 1) frequency = 1;
  const points = [];
  // 计算起始点与终点距离
  const distance = dist(controlPoints[0], controlPoints[3]);
  // 分割曲线的步数：起始点与终点距离 * 步频
  const steps = distance * frequency;
  for (let i = 0; i <= steps; i++) points.push(getBezierCurvePoint(controlPoints, i / steps));
  return points;
};
